#ifndef CPU_INSTR_H
#define CPU_INSTR_H

#include "types.h"

//向端口读取数据
static inline uint8_t inb(uint16_t  port) {
	uint8_t rv;
    //  %[p], %[v] 这是固定的写法， 从端口P 读数据， 数据写到 V 中，  [v]"=a" (rv)， 将 V 与 a 寄存器关联， 并且从rv 中去读取，  
    //【p]"d"(port) 将 p 与d 寄存器相关联， 并且 向port 变量中去写
	__asm__ __volatile__("inb %[p], %[v]" : [v]"=a" (rv) : [p]"d"(port));
	return rv;
}
//读取16字节的数据
static inline uint16_t inw(uint16_t  port) {
	uint16_t rv;
	__asm__ __volatile__("in %1, %0" : "=a" (rv) : "dN" (port));
	return rv;
}


//向端口数据
static inline void outb(uint16_t port, uint8_t data) {
    //outb %[v], %[p] 这也是固定的写法， [p]"d" (port), [v]"a" (data)，将 p , v  与 特定的 寄存器，特定的局部变量相关联
	__asm__ __volatile__("outb %[v], %[p]" : : [p]"d" (port), [v]"a" (data));
}

//关中断
static inline void cli() {
	__asm__ __volatile__("cli");
}
//开中断

static inline void sti() {
	__asm__ __volatile__("sti");
}

//设置gdt 表的内联函数
static inline void lgdt(uint32_t start, uint32_t size) {
	struct {
		uint16_t limit;
		uint16_t start15_0;   
		uint16_t start31_16;  
	} gdt;

	gdt.start31_16 = start >> 16;
	gdt.start15_0 = start & 0xFFFF;
	gdt.limit = size - 1;
// 注意， 这里的 gdt 应该是 已经取了 数组地址处的值 ， 而不应该是 地址了，因为如果是地址的化 ，  类似 这种操作  gdt.start31_16 = start >> 16; 解释不通。
	__asm__ __volatile__("lgdt %[g]"::[g]"m"(gdt));
}

//读取cr0 寄存器
static inline uint32_t read_cr0() {
	uint32_t cr0;
	__asm__ __volatile__("mov %%cr0, %[v]":[v]"=r"(cr0));
	return cr0;
}
//写 cr0
static inline void write_cr0(uint32_t v) {
	__asm__ __volatile__("mov %[v], %%cr0"::[v]"r"(v));
}


//进行远眺转
static inline void far_jump(uint32_t selector, uint32_t offset) {
	uint32_t addr[] = {offset, selector };
	__asm__ __volatile__("ljmpl *(%[a])"::[a]"r"(addr));

}

#endif